package cn.mrcode.fd.utils.mybatis.page;

import org.apache.ibatis.executor.statement.RoutingStatementHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Connection;
import java.util.Properties;

/**
 * Created by zhuqiang on 2015/5/14.
 */
@Intercepts({
        @Signature(method = "prepare", type = StatementHandler.class, args = {Connection.class})})
//标识拦截StatementHandler
public class PageHelper implements Interceptor {
    Logger log =  LoggerFactory.getLogger(this.getClass());
    /**
     * 拦截后要执行的方法，
     * 在拦截之前，也会经过下面类似的步骤。在BaseStatementHandler中，创建parameterHandler和resultSetHandler
     */
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        RoutingStatementHandler handler = (RoutingStatementHandler) invocation.getTarget();
        StatementHandler delegate = (StatementHandler)PageHelperUtil.ReflectUtil.getFieldValue(handler, "delegate");
        BoundSql boundSql = delegate.getBoundSql();//获取该mapper映射的参数信息和传递的参数信息
        Object params = boundSql.getParameterObject(); //获得传递的参数

        Page localPage = getLocalPage();
        PageHelperUtil.removeLocalPage();
        /*log.info("再次获取当前线程ThreadLocal：" + getLocalPage());*/
        /*if (localPage instanceof Page<?>) {*/
        if(localPage != null){
            System.out.println("localPage不能与null" + localPage);
            MappedStatement mappedStatement = (MappedStatement) PageHelperUtil.ReflectUtil.getFieldValue(delegate, "mappedStatement"); //获取mapper方法与xml的映射信息
            Connection connection = (Connection) invocation.getArgs()[0];
            String sql = boundSql.getSql();
            PageHelperUtil.setTotalRecord(localPage, params,mappedStatement, connection);
            PageHelperUtil.ReflectUtil.setFieldValue(boundSql, "sql", PageHelperUtil.getPageSql(localPage, sql)); //把客户端提交的sql语句替换成分页sql语句
        }
        return invocation.proceed();
    }

    /**
     * 拦截器对应的封装原始对象的方法，拦截之前先执行此方法
     */
    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    /**
     * 设置注册拦截器时设定的属性,启动容器初始化的时候就赋值了
     */
    @Override
    public void setProperties(Properties properties) {
        PageHelperUtil.setDatabaseType(properties.getProperty("databaseType"));
    }

    /**
     * 设置page参数
     *
     * @param page
     */
    public static void setLocalPage(Page page) {
        PageHelperUtil.setLocalPage(page);
    }
    /**
     * 获取Page参数
     *
     * @return
     */
    public static Page getLocalPage() {
        return PageHelperUtil.getLocalPage();
    }
}
